// Copyright (c) 2023 Institute of Software, Chinese Academy of Sciences
// Ripple is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
//          http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
package ripple.test.abort;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import ripple.client.RippleClient;
import ripple.common.DebugTool;
import ripple.common.entity.NodeMetadata;
import ripple.server.RippleServer;

/**
 * @author Zhen Tang
 */
public class TryTestStarOverlay {

    private static int SERVER_COUNT = 10;
    private static int CLIENTS_PER_SERVER = 1;
    private static String DATABASE_PATH = "data";

    public static void run(int serverCount, int clientPreServer, String databasePath) {
        SERVER_COUNT = serverCount;
        CLIENTS_PER_SERVER = clientPreServer;
        DATABASE_PATH = databasePath;
        main(null);
    }

    public static void main(String[] args) {
        try {
            Files.createDirectories(Paths.get(DATABASE_PATH));

            DebugTool.cleanDirectory(new File(DATABASE_PATH));

            List<RippleServer> serverList = new ArrayList<>();
            List<RippleClient> clientList = new ArrayList<>();
            List<NodeMetadata> nodeList = new ArrayList<>();

            System.out.println("start create server");
            System.in.read();

            int i = 0;
            for (i = 0; i < SERVER_COUNT; i++) {
                int serverId = i + 1;
                String storageLocation = DATABASE_PATH + "/server-" + serverId + ".db";
                RippleServer rippleServer = RippleServer.starProtocol(serverId, storageLocation);
                System.out.println("before server " + serverId + " start");
                System.in.read();
                rippleServer.start();
                System.out.println("after server " + serverId + " start");
                System.in.read();
                serverList.add(rippleServer);
                System.out.println("[" + SimpleDateFormat.getDateTimeInstance().format(new Date(System.currentTimeMillis())) + "] "
                        + "Node " + rippleServer.getId() + ": " + rippleServer.getAddress() + ", API port = " + rippleServer.getApiPort() + ", UI port = " + rippleServer.getUiPort());
                nodeList.add(new NodeMetadata(serverList.get(i).getId(), serverList.get(i).getAddress(), serverList.get(i).getApiPort()));
                if (serverId > 80) {
                    System.in.read();
                }
            }
            System.in.read();
            for (i = 0; i < SERVER_COUNT; i++) {
                serverList.get(i).initCluster(nodeList);
            }

            int j = 0;
            for (i = 0; i < SERVER_COUNT; i++) {
                for (j = 0; j < CLIENTS_PER_SERVER; j++) {
                    RippleServer rippleServer = serverList.get(i);
                    String storageLocation = DATABASE_PATH + "/server-" + rippleServer.getId() + "-client-" + (j + 1) + ".db";
                    RippleClient rippleClient = new RippleClient(nodeList, storageLocation);
                    rippleClient.start();
                    clientList.add(rippleClient);
                    System.out.println("Client " + (j + 1) + " for Server " + rippleServer.getId() + ":"
                            + rippleClient.getAddress() + ":" + rippleClient.getUiPort());
                }
            }

            String applicationName = "testApp";
            String key = "test";
            String value = "test";

            for (RippleClient rippleClient : clientList) {
                rippleClient.subscribe(applicationName, key);
            }
            System.in.read();

            clientList.get(0).put(applicationName, key, value);

            // String topic = "test topic";
            // Data data = new Data("test data");
            // serverList.get(0).push(topic, data);
            // System.out.println("Press any key to stop.");
            // System.in.read();
            for (RippleClient rippleClient : clientList) {
                rippleClient.stop();
            }

            for (RippleServer rippleServer : serverList) {
                rippleServer.stop();
            }

        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }
}
